﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using PSE.Framework.UI.Controls.SmartClient.Validation;

namespace PSE.Framework.UI.Controls.SmartClient
{
	[DefaultProperty("Value")]
	public partial class FilePicker : Control, IValidatableObject
	{
		private const string FilePickerValidationRuleName = "FilePickerValidationRule";

		TextBox txtPath;
		Button btSearch_Text;
		Button btSearch_Icon;
		System.Windows.Forms.OpenFileDialog fileDialog;

		public static readonly DependencyProperty WidthPathProperty = DependencyProperty.Register("WidthPath", typeof(double), typeof(FilePicker), new FrameworkPropertyMetadata((double)50));
		public static readonly DependencyProperty WidthButtonProperty = DependencyProperty.Register("WidthButton", typeof(double), typeof(FilePicker), new FrameworkPropertyMetadata((double)70));
		public static readonly DependencyProperty ShowIconOnButtonProperty = DependencyProperty.Register("ShowIconOnButton", typeof(bool), typeof(FilePicker), new FrameworkPropertyMetadata(false));
		public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(FilePicker), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
		public static readonly DependencyProperty IsRequiredProperty = DependencyProperty.Register("IsRequired", typeof(bool), typeof(FilePicker), new FrameworkPropertyMetadata(false, OnIsRequiredPropertyChanged));
		public static readonly DependencyProperty InvalidFileErrorMessageProperty = DependencyProperty.Register("InvalidFileErrorMessage", typeof(string), typeof(FilePicker), new FrameworkPropertyMetadata("Infra.Controls.Message.ArquivoNaoEncontrado", OnInvalidFileErrorMessagePropertyChanged));
		public static readonly DependencyProperty CanValidateProperty = ValidationManager.CanValidateProperty.AddOwner(typeof(FilePicker));
		public static readonly DependencyProperty ValidationGroupProperty = ValidationManager.ValidationGroupProperty.AddOwner(typeof(FilePicker));
		public static readonly DependencyProperty ClearServiceErrorsProperty = ValidationManager.ClearServiceErrorsProperty.AddOwner(typeof(FilePicker));
		public static readonly DependencyProperty CausesValidationProperty = ValidationManager.CausesValidationProperty.AddOwner(typeof(FilePicker));
		public static readonly DependencyProperty ValidationTriggersProperty = ValidationManager.ValidationTriggersProperty.AddOwner(typeof(FilePicker));
		public static readonly DependencyProperty ValidationRulesProperty = ValidationManager.ValidationRulesProperty.AddOwner(typeof(FilePicker));
		public static readonly DependencyProperty HasErrorProperty = ValidationManager.HasErrorProperty.AddOwner(typeof(FilePicker));
		public static readonly DependencyProperty ErrorsProperty = ValidationManager.ErrorsProperty.AddOwner(typeof(FilePicker));
		public static readonly DependencyProperty ErrorTemplateProperty = ValidationManager.ErrorTemplateProperty.AddOwner(typeof(FilePicker));
		public static readonly DependencyProperty ValidateIfPathExistsProperty = DependencyProperty.Register("ValidateIfPathExists", typeof(bool), typeof(FilePicker), new FrameworkPropertyMetadata(true));

		public double WidthPath
		{
			get { return (double)GetValue(WidthPathProperty); }
			set { SetValue(WidthPathProperty, value); }
		}
		public double WidthButton
		{
			get { return (double)GetValue(WidthButtonProperty); }
			set { SetValue(WidthButtonProperty, value); }
		}
		public bool ShowIconOnButton
		{
			get { return (bool)GetValue(ShowIconOnButtonProperty); }
			set { SetValue(ShowIconOnButtonProperty, value); }
		}
		public string Value
		{
			get { return (string)GetValue(ValueProperty); }
			set { SetValue(ValueProperty, value); }
		}
		public bool IsRequired
		{
			get
			{
				return (bool)GetValue(IsRequiredProperty);
			}
			set
			{
				SetValue(IsRequiredProperty, value);
			}
		}
		public string InvalidFileErrorMessage
		{
			get { return (string)GetValue(InvalidFileErrorMessageProperty); }
			set { SetValue(InvalidFileErrorMessageProperty, value); }
		}

		public bool AddExtension
		{
			get { return fileDialog.AddExtension; }
			set { fileDialog.AddExtension = value; }
		}
		public bool AutoUpgradeEnabled
		{
			get { return fileDialog.AutoUpgradeEnabled; }
			set { fileDialog.AutoUpgradeEnabled = value; }
		}
		public bool CheckFileExists
		{
			get { return fileDialog.CheckFileExists; }
			set { fileDialog.CheckFileExists = value; }
		}
		public bool CheckPathExists
		{
			get { return fileDialog.CheckPathExists; }
			set { fileDialog.CheckPathExists = value; }
		}
		public bool RestoreDirectory
		{
			get { return fileDialog.RestoreDirectory; }
			set { fileDialog.RestoreDirectory = value; }
		}
		public bool ShowHelp
		{
			get { return fileDialog.ShowHelp; }
			set { fileDialog.ShowHelp = value; }
		}
		public bool ShowReadOnly
		{
			get { return fileDialog.ShowReadOnly; }
			set { fileDialog.ShowReadOnly = value; }
		}
		public bool ValidateNames
		{
			get { return fileDialog.ValidateNames; }
			set { fileDialog.ValidateNames = value; }
		}
		public string InitialDirectory
		{
			get { return fileDialog.InitialDirectory; }
			set { fileDialog.InitialDirectory = value; }
		}
		public string DefaultExt
		{
			get { return fileDialog.DefaultExt; }
			set { fileDialog.DefaultExt = value; }
		}
		public string Filter
		{
			get { return fileDialog.Filter; }
			set { fileDialog.Filter = value; }
		}
		public string Title
		{
			get { return fileDialog.Title; }
			set { fileDialog.Title = TryFindResource(value) != null ? (string)TryFindResource(value) : null; }
		}
		public bool ValidateIfPathExists
		{
			get { return (bool)GetValue(ValidateIfPathExistsProperty); }
			set { SetValue(ValidateIfPathExistsProperty, value); }
		}
		public FileAccessRigths FilePermissions
		{
			get
			{
				if (txtPath != null)
				{
					string path = txtPath.Text;
					if (!String.IsNullOrEmpty(path) && System.IO.File.Exists(path))
						return new FileAccessRigths(path);
					else
						return null;
				}
				return null;
			}
		}

		//-------------------------------------------------------------------------------------------------------------

		public FilePicker()
		{
			ValidationManager.InitializeValidation(this);
			this.PrepareDialogs();
		}

		protected virtual void CreateValidations()
		{
			if (this.ValidateIfPathExists && !this.txtPath.ValidationRules.Contains(FilePickerValidationRuleName))
			{
				FilePickerValidationRule FilePickerValidation = new FilePickerValidationRule(this, TextBox.TextProperty);
				FilePickerValidation.Name = FilePickerValidationRuleName;

				this.txtPath.ValidationRules.Add(FilePickerValidation);

				FilePickerValidation.ErrorContent = this.InvalidFileErrorMessage;
				FilePickerValidation.IsEnabled = true;
			}
		}

		protected virtual void UpdateValitadions()
		{
			if (this.ValidationRules.Contains(FilePickerValidationRuleName))
			{
				FilePickerValidationRule FilePickerValidation = this.txtPath.ValidationRules[FilePickerValidationRuleName] as FilePickerValidationRule;
				if (FilePickerValidation != null)
				{
					FilePickerValidation.ErrorContent = this.InvalidFileErrorMessage;
				}
			}
		}

		protected virtual void CreateValidationTriggers()
		{
			EventValidationTrigger trigger = new EventValidationTrigger(ValidationTriggerScope.Self, LostFocusEvent);
			trigger.ContinueRoutingOnError = true;
			if (!this.ValidationTriggers.Contains(trigger))
			{
				this.ValidationTriggers.Add(trigger);
			}
		}

		static void OnInvalidFileErrorMessagePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			FilePicker instance = d as FilePicker;
			if (instance != null)
				instance.UpdateValitadions();
		}

		static void OnIsRequiredPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			FilePicker instance = d as FilePicker;
			if (instance != null)
				instance.UpdateValitadions();
		}

		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			txtPath = this.GetTemplateChild("PART_txtPath") as TextBox;
			btSearch_Text = this.GetTemplateChild("PART_btSearch_Text") as Button;
			btSearch_Icon = this.GetTemplateChild("PART_btSearch_Icon") as Button;

			txtPath.MaxLength = 256;
			btSearch_Text.Click += new RoutedEventHandler(Search_Click);
			btSearch_Icon.Click += new RoutedEventHandler(Search_Click);

			btSearch_Text.Visibility = !ShowIconOnButton ? Visibility.Visible : Visibility.Collapsed;
			btSearch_Icon.Visibility = ShowIconOnButton ? Visibility.Visible : Visibility.Collapsed;

			Binding bd = new Binding("Value");
			bd.Mode = BindingMode.TwoWay;
			bd.UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;
			bd.RelativeSource = RelativeSource.TemplatedParent;
			this.txtPath.SetBinding(TextBox.TextProperty, bd);

			CreateValidations();
			CreateValidationTriggers();

			if (this.IsRequired)
				this.txtPath.IsRequired = this.IsRequired;
		}

		void Search_Click(object sender, RoutedEventArgs e)
		{
			if (!String.IsNullOrEmpty(txtPath.Text))
				fileDialog.InitialDirectory = txtPath.Text;

			switch (fileDialog.ShowDialog())
			{
				case System.Windows.Forms.DialogResult.OK:
					if (fileDialog.FileNames.Length > 0)
					{
						Value = fileDialog.FileName;
						txtPath.Text = fileDialog.FileName;
					}
					break;
				default:
					break;
			}
		}

		void PrepareDialogs()
		{
			fileDialog = new System.Windows.Forms.OpenFileDialog();
			fileDialog.DefaultExt = DefaultExt;
			fileDialog.Filter = Filter;
			fileDialog.Title = Title;
			fileDialog.AddExtension = AddExtension;
			fileDialog.AutoUpgradeEnabled = AutoUpgradeEnabled;
			fileDialog.CheckFileExists = CheckFileExists;
			fileDialog.CheckPathExists = CheckPathExists;
			fileDialog.InitialDirectory = InitialDirectory;
			fileDialog.RestoreDirectory = RestoreDirectory;
			fileDialog.ShowHelp = ShowHelp;
			fileDialog.ShowReadOnly = ShowReadOnly;
			fileDialog.ValidateNames = ValidateNames;
			fileDialog.Multiselect = false;
		}

		//-------------------------------------------------------------------------------------------------------------

		public bool CanValidate
		{
			get { return (bool)GetValue(CanValidateProperty); }
		}
		public string ValidationGroup
		{
			get { return (string)GetValue(ValidationGroupProperty); }
			set { SetValue(ValidationGroupProperty, value); }
		}
		public bool ClearServiceErrors
		{
			get { return (bool)GetValue(ClearServiceErrorsProperty); }
			set { SetValue(ClearServiceErrorsProperty, value); }
		}
		public bool CausesValidation
		{
			get { return (bool)GetValue(CausesValidationProperty); }
			set { SetValue(CausesValidationProperty, value); }
		}
		public bool HasError
		{
			get { return (bool)GetValue(HasErrorProperty); }
		}
		public bool Validate()
		{
			return ValidationManager.Validate(this);
		}
		public bool Validate(DependencyProperty property)
		{
			return ValidationManager.Validate(this, property);
		}
		public bool ValidateParentContainer()
		{
			return ValidationManager.ValidateParentContainer(this);
		}
		public ValidationTriggerCollection ValidationTriggers
		{
			get { return (ValidationTriggerCollection)GetValue(ValidationTriggersProperty); }
		}
		public ValidationRuleCollection ValidationRules
		{
			get { return (ValidationRuleCollection)GetValue(ValidationRulesProperty); }
		}
		public ReadOnlyObservableCollection<ValidationError> Errors
		{
			get { return (ReadOnlyObservableCollection<ValidationError>)GetValue(ErrorsProperty); }
		}
		public ControlTemplate ErrorTemplate
		{
			get { return (ControlTemplate)GetValue(ErrorTemplateProperty); }
			set { SetValue(ErrorTemplateProperty, value); }
		}
	}
}